<template>
  <basic-layout show-tab-bar>
    <custom-nav-bar title="图表" />
    <nut-menu>
      <nut-menu-item v-model="type" :options="tabvalueList" @change="initMultiBarChart" />
      <nut-menu-item v-model="interval" :options="TimeList" @change="initMultiBarChart" />
    </nut-menu>
    <div :class="show ? 'blurDiv' : ''">
      <div class="m-4">
        <span v-if="interval === 'week'">本周</span>
        <span v-else-if="interval === 'month'">本月</span>
        <span v-else>今年</span>
      </div>
      <nut-divider />
      <nut-grid :column-num="2">
        <nut-grid-item>总支出: ¥{{ total() }}</nut-grid-item>
        <nut-grid-item>平均值: ¥{{ average() }}</nut-grid-item>
      </nut-grid>
      <view class="bar-chart">
        <EChart ref="barChat" canvas-id="bar-canvas" />
      </view>
      <nut-divider />
      <div class="ranking">
        <div class="m-4">
          <span>{{ type === '0' ? '支出' : '收入' }}排行榜</span>
        </div>
        <ul v-if="targetRecords().length > 0" class="tag-list">
          <li v-for="(item, index) in groupByTag()" :key="index" class="tag-item">
            <nut-row>
              <nut-col :span="2">&#12288;</nut-col>
              <nut-col :span="4" class="selected">
                <div class="tagItemImg relative h-0 pb-full w-full">
                  <img :src="`https://img.xxsoftware.top/svg/${item.tag.name}.svg`" mode="widthFix" />
                </div>
              </nut-col>
              <nut-col :span="2">&#12288;</nut-col>
              <nut-col :span="6">
                <div :style="`line-height: ${lineHeight};`">{{ item.tag.value }}</div>
              </nut-col>
              <nut-col :span="6">
                <div :style="`line-height: ${lineHeight};`">{{ item.percentage }}%</div>
              </nut-col>
              <nut-col :span="4">
                <div :style="`line-height: ${lineHeight};`">￥{{ item.amount }}</div>
              </nut-col>
            </nut-row>
          </li>
        </ul>
        <div v-else>
          <Blank />
        </div>
      </div>
    </div>
    <nut-overlay v-model:visible="show" close-on-click-overlay="false">
      <div class="overlay-wrapper">
        <div class="overlay-content">表格功能需要登录</div>
      </div>
    </nut-overlay>
  </basic-layout>
</template>
<script setup lang="ts">
import Taro, { useReady, useDidShow } from '@tarojs/taro';
import dayjs from 'dayjs';
import { useTagStore, useAuthStore } from '@/store';
import { twoDecimalPlaces } from '@/lib/decimal';
import clone from '@/lib/clone';
const AuthStore = useAuthStore();
const show = ref(AuthStore.isLogin);
const lineHeight = ref('');
useDidShow(() => {
  show.value = AuthStore.isLogin;
  console.log(show.value);
  if (groupByTag().length) {
    Taro.nextTick(() => {
      Taro.createSelectorQuery()
        .select('.tag-item')
        .boundingClientRect()
        .exec(res => {
          if (res) {
            lineHeight.value = `${res[0].height}px`;
          }
        });
      initMultiBarChart();
    });
  }
});
type Group = {
  tag: TagItem;
  amount: number;
  percentage: number;
};
useReady(() => {
  initMultiBarChart();
});
const barChat = ref<any>();
const type = ref('0');
const interval = ref('week');
const tabvalueList = [
  { text: '支出', value: '0' },
  { text: '收入', value: '1' }
];
const TimeList = [
  { text: '本周', value: 'week' },
  { text: '本月', value: 'month' },
  { text: '今年', value: 'year' }
];

function groupByTag(): Group[] {
  const tags: string[] = [];
  let result: Group[] = [];
  let r: RecordItem;
  for (r of targetRecords()) {
    const index = tags.indexOf(r.tag.name);
    if (index < 0) {
      tags.push(r.tag.name);
      result.push({ tag: r.tag, amount: Number(r.amount), percentage: 0 });
    } else {
      result[index].amount += Number(r.amount);
    }
  }
  for (let i = 0; i < result.length; i++) {
    result[i].percentage = twoDecimalPlaces((Number(result[i].amount) * 100) / total());
  }
  result = result.sort((b, a) => a.percentage - b.percentage);
  return result;
}

function initMultiBarChart() {
  const x = [...groupByInterval().keys()];
  const y = [...groupByInterval().values()];
  const options = {
    grid: {
      top: '5%',
      bottom: '10%'
    },
    xAxis: {
      data: x,
      axisTick: {
        interval: 0,
        lineStyle: {
          opacity: 1
        }
      },
      axisLabel: {
        interval: 0,
        fontSize: 8,
        color: '#999999'
      }
    },
    yAxis: {
      axisLine: {
        lineStyle: {
          opacity: 0
        }
      },
      splitLine: {
        lineStyle: {
          opacity: 1
        }
      },
      axisLabel: undefined,
      axisTick: undefined
    },
    series: [
      {
        type: 'line',
        data: y
      },
      {
        name: '平均线',
        type: 'line',
        data: toArray(average(), x.length),
        symbol: 'none',
        lineStyle: {
          type: 'dashed',
          color: '#999999',
          width: 1,
          opacity: 0.5
        }
      },
      {
        name: '最大值',
        type: 'line',
        data: toArray(Math.max(...y), x.length),
        symbol: 'none',
        lineStyle: {
          color: '#999999',
          width: 1,
          opacity: 0.5
        }
      }
    ]
  };
  Taro.nextTick(() => {
    barChat.value.refresh(options);
  });
}

function groupByWeek(records: RecordItem[]): Map<string, number> {
  const keys = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
  const result = new Map<string, number>();
  let i: number;
  // 初始化
  for (i = 0; i < keys.length; i++) {
    result.set(keys[i], 0);
  }
  let r: RecordItem;
  for (r of records) {
    const key = keys[dayjs(r.createAt).day()];
    const amount = result.get(key) as number;
    result.set(key, amount + Number(r.amount));
  }
  return result;
}
function days() {
  const [year, month] = [dayjs().year(), dayjs().month()];
  const d = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

  if ((year % 4 === 0 && year % 100 !== 0) || (year % 100 === 0 && year % 400 === 0)) {
    if (month === 1) {
      return 29;
    }
    return d[month];
  }
  return d[month];
}

function groupByMonth(records: RecordItem[]): Map<string, number> {
  const keys: string[] = [];
  const result = new Map<string, number>();
  let i: number;
  // 初始化
  for (i = 1; i < days(); i++) {
    keys.push(i.toString());
  }
  for (i = 0; i < keys.length; i++) {
    result.set(keys[i], 0);
  }
  let r: RecordItem;
  for (r of records) {
    const key = dayjs(r.createAt).date().toString();
    const amount = result.get(key) as number;
    result.set(key, amount + Number(r.amount));
  }
  return result;
}

function groupByYear(records: RecordItem[]): Map<string, number> {
  const keys = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
  const result = new Map<string, number>();
  let i: number;
  // 初始化
  for (i = 0; i < keys.length; i++) {
    result.set(keys[i], 0);
  }
  let r: RecordItem;
  for (r of records) {
    const key = keys[dayjs(r.createAt).month()];
    const amount = result.get(key) as number;
    result.set(key, amount + Number(r.amount));
  }
  return result;
}

const tagStore = useTagStore();
function targetRecords(): RecordItem[] {
  const now = dayjs();
  return clone<RecordItem[]>(tagStore.recordList)
    .filter(item => item.type === type.value)
    .filter(item => dayjs(item.createAt).isSame(now, interval.value));
}

function groupByInterval(): Map<string, number> {
  let result = new Map<string, number>();
  switch (interval.value) {
    case 'week':
      result = groupByWeek(targetRecords());
      break;
    case 'month':
      result = groupByMonth(targetRecords());
      break;
    case 'year':
      result = groupByYear(targetRecords());
      break;
    default:
      break;
  }
  return result;
}

function total() {
  const amounts = [...groupByInterval().values()];
  let sum = 0;
  for (let i = 0; i < amounts.length; i++) {
    sum += amounts[i];
  }
  return sum;
}
function average() {
  const now = dayjs();
  switch (interval.value) {
    case 'week':
      return twoDecimalPlaces(total() / (now.day() + 1));
    case 'month':
      return twoDecimalPlaces(total() / now.date());
    case 'year':
      return twoDecimalPlaces(total() / (now.month() + 1));
    default:
      return 0;
  }
}
function toArray(value: number, length: number): number[] {
  const result: number[] = [];
  for (let i = 0; i < length; i++) {
    result.push(value);
  }
  return result;
}

definePageConfig({
  navigationBarTitleText: '图表'
});
</script>

<style lang="scss">
.bar-chart {
  width: 100%;
  min-height: 500rpx;
  flex: 1;
}
.overlay-wrapper {
  display: flex;
  height: 100%;
  align-items: center;
  justify-content: center;
  .overlay-content {
    display: flex;
    width: 150px;
    height: 150px;
    background: #fff;
    border-radius: 8px;
    align-items: center;
    justify-content: center;
    color: var(--nut-primary-color, #fa2c19);
  }
}
.blurDiv {
  filter: blur(2px);
}
</style>
